package com.example.mdc.logback.common.config.okhttp;

import okhttp3.*;
import okio.Buffer;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author:      liu_pc
 * Date:        2023/8/7
 * Description: OKHttp日志拦截器
 * Version:     1.0
 */
public class OkHttpLoggingInterceptor implements Interceptor {
    private final Logger logger = LoggerFactory.getLogger(OkHttpLoggingInterceptor.class);

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        Request request = chain.request();
        try {
            StringBuilder builder = new StringBuilder();

            // 构建请求信息
            builder.append("\r\n请求url: ").append(request.url());
            builder.append("\r\n请求消息头: \r\n").append(request.headers());
            String method = request.method();

            // POST请求单独处理
            if (HttpMethod.POST.name().equals(method)) {
                builder.append("\r\n请求body: ").append(getPostRequestBody(request));
            }

            Response response = chain.proceed(request);

            // 构建响应信息
            builder.append("\r\n返回数据: ").append(getResponseBodyString(response));

            logger.info("OkHttp请求信息: {}", builder);

            return response;
        } catch (IOException e) {
            logger.error("Okhttp请求异常", e);
            throw e;
        }
    }

    /**
     * 获取POST请求的请求体
     * @param request 请求体
     * @return 请求体的字符串表示
     * @throws IOException IO异常
     */
    private String getPostRequestBody(Request request) throws IOException {
        RequestBody body = request.body();
        if (body != null) {
            if (body instanceof FormBody) {
                return getFormBodyString((FormBody) body);
            } else {
                return getRequestBodyString(body);
            }
        }
        return "";
    }

    /**
     * 获取FormBody的字符串表示
     * @param formBody 请求体
     * @return 请求体的字符串表示
     */
    private String getFormBodyString(FormBody formBody) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < formBody.size(); i++) {
            builder.append(formBody.encodedName(i))
                    .append(" = ")
                    .append(formBody.encodedValue(i))
                    .append(" ");
        }
        return builder.toString();
    }


    /**
     * 获取请求体的字符串表示
     * @param body 请求体
     * @return 请求体字符串
     * @throws IOException IO异常
     */
    private String getRequestBodyString(RequestBody body) throws IOException {
        Buffer buffer = new Buffer();
        body.writeTo(buffer);
        return buffer.readString(StandardCharsets.UTF_8);
    }


    /**
     * 获取响应体的字符串表示
     * @param response 响应体
     * @return 响应体转字符串
     * @throws IOException IO异常
     */
    private String getResponseBodyString(Response response) throws IOException {
        ResponseBody responseBody = response.peekBody(1024L * 1024);
        return responseBody.string();
    }
}